package com.hy.example.shared.dbaccess.listener;

import com.hy.example.shared.dbaccess.entity.AbstractAuditable;
import com.hy.example.shared.dbaccess.entity.AbstractAuditable;
import com.hy.example.shared.utils.CustomAuditorAware;
import com.hy.example.shared.dbaccess.entity.AbstractAuditable;
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.Objects;

public class AuditingHandler extends IsNewAwareAuditingHandler {

    private final CustomAuditorAware auditorAware;

    public AuditingHandler(MappingContext<?,?> mappingContext, CustomAuditorAware userCustomAuditorAware) {
        super(PersistentEntities.of(mappingContext));
        setAuditorAware(userCustomAuditorAware);
        this.auditorAware = userCustomAuditorAware;
    }

    @Override
    public Object markCreated(Object source) {
        Assert.notNull(source, "Entity must not be null");
        if (source instanceof AbstractAuditable abstractAuditable) {
            auditorAware.getCurrentAuditorNickName()
                    .ifPresent(name -> {
                        if (Objects.isNull(abstractAuditable.getCreatedByName())) {
                            abstractAuditable.setCreatedByName(name);
                        }
                        abstractAuditable.setLastModifiedByName(name);
                    });
            auditorAware.getCurrentAuditor()
                    .ifPresent(id -> {
                        if (abstractAuditable.getCreatedBy().isEmpty()) {
                            abstractAuditable.setCreatedBy(id);

                        }
                        abstractAuditable.setLastModifiedBy(id);
                    });
            abstractAuditable.setCreatedDate(LocalDateTime.now());
            abstractAuditable.setLastModifiedDate(LocalDateTime.now());
            return abstractAuditable;
        } else {
            return super.markCreated(source);
        }
    }

    @Override
    public Object markModified(Object source) {
        Object marked = super.markModified(source);
        if (marked instanceof AbstractAuditable abstractAuditable
        && Objects.isNull(abstractAuditable.getLastModifiedByName())) {
                auditorAware.getCurrentAuditorNickName()
                        .ifPresent(abstractAuditable::setLastModifiedByName);
        }
        return marked;
    }
}
